#include <algorithm>
#include <iostream>
#include <vector>
#include "../config.h"
#include <cv.h>
#include <cxcore.h>
#include <highgui.h>
#include <IfImg.h>
#include <time.h>
#define  M 10

typedef struct node
{
	int id;
	double val;
}VertexNode, *VertexNodePtr;

bool operator > (const VertexNode & v1, const VertexNode & v2 )
{
	return v1.val > v2.val;
}

bool operator == (const VertexNode & v1, const VertexNode & v2)
{
	return v1.id == v2.id;
}

typedef struct PathInfoStruct
{
	bool flag;
	double val;
	std::vector<int> ids;
}PathInfo;

void ConnectedVertexList(int a[][M], int id, std::vector<int> & list, std::vector<PathInfo> & path)
{
    for (int i = 0; i < M; ++i)
	{
		if (id == i || path[i].flag == true || a[i][id] == INT_MAX)
			continue;
		list.push_back(i);
	}
}

void Dijkstra(int a[M][M], int id, std::vector<PathInfo> & path)
{
	using namespace std;
	// Initialize
	for (int i = 0; i < M; ++i)
	{
		PathInfo vnode = {false, INT_MAX};
		path.push_back(vnode);
	}
	path[id].val = 0;
	path[id].flag = true;
	path[id].ids.push_back(id);

	typedef  vector<VertexNode> MinHeap;
	MinHeap minheap;
	VertexNode v0 = {id, 0};
	minheap.push_back(v0);

	while (!minheap.empty())
	{
		//here we find a shortest vertex
		pop_heap(minheap.begin(), minheap.end(), operator >);
		MinHeap::iterator last = minheap.end() - 1;
		VertexNode v0 = *last;
		minheap.erase(last);
		path[v0.id].flag = true;

		//update min-heap tree
		vector<int> adjacent;
		ConnectedVertexList(a, v0.id, adjacent, path);
		int adjacentNum = static_cast<int>(adjacent.size());
		for (int i = 0; i < adjacentNum; ++i)
		{
			VertexNode vi;
			vi.id = adjacent[i];
			vi.val = min(a[v0.id][vi.id] + path[v0.id].val, path[vi.id].val);
			if (path[vi.id].val > vi.val)
			{
				path[vi.id].val = vi.val;
				path[vi.id].ids = path[v0.id].ids;
				path[vi.id].ids.push_back(vi.id);
			}
			MinHeap::iterator it = find(minheap.begin(), minheap.end(), vi);
			if (it != minheap.end())
				minheap.erase(it);
			minheap.push_back(vi);
			push_heap(minheap.begin(), minheap.end(), operator >);
		}
	}
}

void print(const std::vector<PathInfo> & path)
{
	using namespace std;
	int n = static_cast<int>(path.size());
	for (int i = 0; i < n; ++i)
	{
		cout << i << " : " ;
		int pathnum = static_cast<int>(path[i].ids.size());
		for (int j = 0; j < pathnum; ++j)
		    cout << path[i].ids[j] << " ";
		cout << "distance : " << path[i].val << endl;
	}
}
char * BUFFER = NULL;
char * CvImageBuffer = NULL;
IplImage * EndoscopeImage;
IplImage * GreyImage;
VOID CALLBACK lpCallBackProc(IMGEVENTTABLE Event, DWORD dwFrameCnt, DWORD dwUser)
{
	for (int j = 0; j < 480; ++j)
	{
		if (j % 2 == 0)
		{
			memcpy(CvImageBuffer + (/*479 - */j) * 640 * 3, BUFFER + j / 2 * 640 * 3, 640 * 3);
		}
		else
		{
			memcpy(CvImageBuffer + (/*479 -*/ j) * 640 * 3, BUFFER + (j / 2 + 240) * 640 * 3, 640 * 3);
		}
	}	


	//cvCvtColor(EndoscopeImage, GreyImage, CV_BGR2GRAY);
	//cvShowImage("Grey Image", GreyImage);
	CvPoint2D32f pts[49];
	int count;
	int ret = cvFindChessboardCorners(EndoscopeImage, cvSize(7, 7), pts, &count);
	cvDrawChessboardCorners(EndoscopeImage, cvSize(7, 7), pts, count, ret);
	cvShowImage("Endoscope Image", EndoscopeImage);

}
int main1()
{
	using namespace std;
	HANDLE ImageCardHandle = ImgOpen("IFIMGMEM1");
	if (ImageCardHandle == INVALID_HANDLE_VALUE)
	{
		MessageBox(NULL, "Can't Open Image Card Device!", "Error", MB_OK);
		return 0;
	}

	BUFFER = new char[640 * 480 * 3];
	CvImageBuffer = new char[640 * 480 * 3];

	IMGBUFFERINFO bufinfo;
	bufinfo.pBufferAddress = BUFFER;
	bufinfo.dwBufferSize = 640 * 480 * 3;
	if (IFIMG_ERROR_SUCCESS != ImgSetBuffer(ImageCardHandle, &bufinfo, IFIMG_COLOR_RGB24))
	{
		MessageBox(NULL, "Buffer Set Error!", "Error", MB_OK);
	}
	IMGEVENTTABLE Mask;
	Mask.dwDI = 0x00;
	Mask.dwFrame = 0x01;
	Mask.dwTrigger = 0;
	if (IFIMG_ERROR_SUCCESS != ImgSetEventMask(ImageCardHandle, &Mask))
	{
	MessageBox(NULL, "SetEventMask Error!", "Error", MB_OK);
	}
	IMGEVENTREQ Event;
	Event.hWnd = NULL;
	Event.uMessage = NULL;
	Event.hEvent = NULL;
	Event.pCallBackProc = (PIMGCALLBACK)lpCallBackProc;
	if (IFIMG_ERROR_SUCCESS != ImgSetEvent(ImageCardHandle, &Event))
	{
	MessageBox(NULL, "SetEvent Error!", "Error", MB_OK);
	}

	cvNamedWindow("Endoscope Image");
	EndoscopeImage = cvCreateImage(cvSize(640, 480), IPL_DEPTH_8U, 3);
	cvSetData(EndoscopeImage, CvImageBuffer, EndoscopeImage->widthStep);
	GreyImage = cvCreateImage(cvSize(640, 480), IPL_DEPTH_8U, 1);
	if (IFIMG_ERROR_SUCCESS != ImgStartCapture(ImageCardHandle, 0, IFIMG_DMACAPTURE_START))
	{
	MessageBox(NULL, "Start Capture Error!", "Error", MB_OK);
	}

	cvWaitKey();
	ImgStopCapture(ImageCardHandle, IFIMG_IMMEDIATE_STOP);
	ImgClose(ImageCardHandle);
	delete[] BUFFER;
	cvReleaseImage(&GreyImage);
	cvReleaseImage(&EndoscopeImage);
	return 1;
}

